<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <div>hello</div>
    <div>hello1</div>
    <div>hello2</div>
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
    </ul>
  </div>
</body>

<script>
  // .1 怎么将dome 转换成 vnode
    class Vnode {
      constructor(tag,data,value,type){
        this.tag = tag&&tag.toLowerCase();
        this.data = data;// 节点属性
        this.value = value;//文本内容
        this.type = type;
        this.children =[]
      }
      appendChild(vNode){
        this.children.push(vNode)
      }
    }
      // 使用递归
      // vue 栈结构

      // 将dome 生成vnode
     function getVnode(node){
          let nodeType = node.nodeType;
          let _vnode = null;
          if(nodeType===1){
            let targName = node.nodeName;
            let attrs = node.attributes // attributes 返回是个伪数组
            let _attrObject = {}
            for(let i = 0;i<attrs.length;i++){ // attrs[i] 是属性节点
              _attrObject[attrs[i].nodeName] =attrs[i].nodeValue
            }
            _vnode = new Vnode(targName,_attrObject,undefined,nodeType)
            let childNodes = node.childNodes
            for(let i = 0 ;i<childNodes.length;i++){
              _vnode.appendChild(getVnode(childNodes[i]))
            }
          } else if(nodeType ===3){
            _vnode = new Vnode(undefined,undefined,node.nodeValue,nodeType)
          }
          return _vnode
      }
    
      let vnode = getVnode(root)
      
  // .2 怎么将vnode 转换成 dome 
      function paseVnode(vnode){
        let type = vnode.type
        let _node =null;
        if(type===3){
          return document.createTextNode(vnode.value)
        } else if(type ===1){
          _node = document.createElement(vnode.tag);
          //属性
          let data= vnode.data;
          Object.keys(data).forEach(item =>{
            let attrName = item;
            let attrValue = data[item];
            _node.setAttribute(attrName,attrValue);
          })
          //子元素
          let children = vnode.children;
          children.forEach(subvnode =>{
            _node.appendChild(paseVnode(subvnode))
          })

          return _node
        }
      }
      let paseDome = paseVnode(vnode);
      console.log(paseDome)
      // vue  内部实现
      // 模板 =>  ast 抽象语法树  最消耗性能   故保存抽象语法树  之前代码没做
      // ast => vNode 
      // vnode => dome

      // 

</script>
</html>